Skip to content

ZOOKEEPER-4947: Stop the send loop after SASL authentication fails - #2443

Open
1fanwang wants to merge 3 commits into
apache:masterfrom
1fanwang:fix-zookeeper-4947-auth-failed-close
Open

1fanwang wants to merge 3 commits into
apache:masterfrom
1fanwang:fix-zookeeper-4947-auth-failed-close

Conversation

@1fanwang

@1fanwang 1fanwang commented Aug 25, 2026

Copy link
Copy Markdown

After SASL authentication fails, the send thread can remain in a transport wait. It eventually exits; the event thread already stops. Break out at the authentication-failure branch before another transport wait, so the existing cleanup runs without caller close. The client retains AUTH_FAILED; explicit close still sets CLOSED.

https://issues.apache.org/jira/browse/ZOOKEEPER-4947

Testing Done

The bad-DIGEST fixture uses a real file-backed loopback server and a 30-second session. It logs shutdown before close with a one-second bound per thread, then asserts shutdown, the retained failure state and request error.

From this PR's checkout, apply only its test changes to the baseline:

base=5a201d633fd90a14ba76795683be36b05baedff0
git worktree add --detach ../zk-auth-before "$base"
git diff "$base" HEAD -- zookeeper-server/src/test/java | git -C ../zk-auth-before apply

With JDK 25 and cached Maven dependencies, run this in the baseline and PR checkouts:

for socket in NIO Netty; do
  if mvn -B -ntp --offline -T 1 -Pfull-build -pl zookeeper-server -am test \
    -Dtest=SaslAuthFailTest#testBadSaslAuthNotifiesWatch \
    "-Dzookeeper.clientCnxnSocket=org.apache.zookeeper.ClientCnxnSocket${socket}" \
    -Dsurefire-forkcount=1 -Dsurefire.rerunFailingTestsCount=0 \
    -Dsurefire.failIfNoSpecifiedTests=false -DfailIfNoTests=false \
    -DredirectTestOutputToFile=false; then status=0; else status=$?; fi
  echo "$socket exit=$status"
done

Both baseline runs exited 1 with:

org.opentest4j.AssertionFailedError: Client threads should stop after SASL authentication fails ==> expected: <true> but was: <false>

The baseline observations below are NIO followed by Netty:

2026-09-19 23:59:20,939 [myid:] - INFO  [main:o.a.z.t.SaslAuthFailTest@101] - SASL failure shutdown without close: threadsStopped=false, state=AUTH_FAILED
2026-09-19 23:59:30,905 [myid:] - INFO  [main:o.a.z.t.SaslAuthFailTest@101] - SASL failure shutdown without close: threadsStopped=false, state=AUTH_FAILED

After the fix, both runs exited 0:

2026-09-19 23:59:39,562 [myid:] - INFO  [main:o.a.z.t.SaslAuthFailTest@101] - SASL failure shutdown without close: threadsStopped=true, state=AUTH_FAILED
2026-09-19 23:59:48,097 [myid:] - INFO  [main:o.a.z.t.SaslAuthFailTest@101] - SASL failure shutdown without close: threadsStopped=true, state=AUTH_FAILED

ZooKeeper.close() treated AUTH_FAILED clients as already closed and skipped prompt shutdown of their connection threads.

Signed-off-by: 1fanwang <1fannnw@gmail.com>

@kezhuw kezhuw left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@kezhuw

kezhuw commented Sep 18, 2026

Copy link
Copy Markdown
Member

Reproduction Steps

  1. Configure SASL authentication with invalid credentials
  2. Connect to ZooKeeper server
  3. Watch receives KeeperState.AuthFailed event
  4. Call zookeeper.close()
  5. Observe SendThread/EventThread still running via thread dump

I checked the reproduction steps from ZOOKEEPER-4947 and think the behavior is temporary as AUTH_FAILED does not break send loop eagerly. After connection failure, SendThread and EventThread will be run out main loop eventally.

@kezhuw

kezhuw commented Sep 20, 2026

Copy link
Copy Markdown
Member

Withdraw my +1.

I think what we need to do is quiting send loop right after AUTH_FAILED.

Signed-off-by: 1fanwang <1fannnw@gmail.com>
Signed-off-by: 1fanwang <1fannnw@gmail.com>
@1fanwang 1fanwang changed the title ZOOKEEPER-4947: Close clients after authentication failure ZOOKEEPER-4947: Stop the send loop after SASL authentication fails Sep 20, 2026
@1fanwang

Copy link
Copy Markdown
Author

Done in 2dd3c44. The send loop now exits on AUTH_FAILED without caller close; the description is corrected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants